{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "from dataclasses import dataclass\n",
    "from typing import List, Tuple\n",
    "\n",
    "import random\n",
    "import vss\n",
    "from crypto import G1, random_scalar, add, multiply, sum_points, CURVE_ORDER"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [],
   "source": [
    "def eval_public_poly(commitments, x):\n",
    "    return sum_points([multiply(com, pow(x, j, CURVE_ORDER)) for j, com in enumerate(commitments)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [],
   "source": [
    "N = 5\n",
    "T = 3\n",
    "\n",
    "@dataclass\n",
    "class Participant:\n",
    "    idx: int\n",
    "    secret: int\n",
    "    shares: List[int]\n",
    "    commitments: List[Tuple[int, int]]\n",
    "    indexed_shares: List[Tuple[int, int]]\n",
    "    secret_key: int = None\n",
    "    public_key: Tuple[int, int] = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "P = []\n",
    "for i in range(N):\n",
    "    secret = random_scalar()\n",
    "    shares, commitments = vss.share(secret, n, t)\n",
    "    indexed_shares = list(zip(range(1, n + 1), shares))\n",
    "    P.append(Participant(i + 1, secret, shares, commitments, indexed_shares))\n",
    "    \n",
    "for i in range(N):\n",
    "    P[i].secret_key = sum(P[j].shares[i] for j in range(N)) % CURVE_ORDER\n",
    "    P[i].public_key = multiply(G1, P[i].secret_key)\n",
    "    assert P[i].public_key == sum_points([\n",
    "        eval_public_poly(P[j].commitments, P[i].idx)\n",
    "        for j in range(N)\n",
    "    ])\n",
    "    \n",
    "    \n",
    "secret_key = sum(P[i].secret for i in range(N)) % CURVE_ORDER\n",
    "public_key = multiply(G1, secret_key)\n",
    "assert public_key == sum_points([P[i].commitments[0] for i in range(N)])\n",
    "\n",
    "G = random.sample(P, T)\n",
    "\n",
    "assert P[i].secret == vss.recover(random.sample(P[i].indexed_shares, T))\n",
    "assert secret_key == vss.recover([(G[k].idx, G[k].secret_key) for k in range(T)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [],
   "source": [
    "b = [random_scalar() for i in range(N)]\n",
    "B = [multiply(G1, b[i]) for i in range(N)]\n",
    "\n",
    "secret_key = ((secret_key) + sum(b)) % CURVE_ORDER\n",
    "public_key = add(public_key, sum_points(B))\n",
    "\n",
    "assert public_key == multiply(G1, secret_key)\n",
    "\n",
    "for i in range(N):\n",
    "    P[i].secret_key = (P[i].secret_key + sum(b)) % CURVE_ORDER\n",
    "    P[i].public_key = add(P[i].public_key, sum_points(B))\n",
    "    assert P[i].public_key == multiply(G1, P[i].secret_key)\n",
    "            \n",
    "assert secret_key == vss.recover([(G[k].idx, G[k].secret_key) for k in range(T)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
